#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <QWheelEvent>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setLayout(ui->gridLayout_global);

    serialDevlInit();
    uiMemInit();
    sendCnt = 0;
    recvCnt = 0;

//    getCircleTime = ui->spinBox_circlesent->value();
//    circleThread = new mythread(this);
//    QObject::connect(circleThread, &mythread::pthreadTimeOut, this, &Widget::circleSendCallBack);

}

//int Widget::getCircleTime = 0;


Widget::~Widget()
{
    delete ui;
}


void Widget::serialDevlInit()
{
    serialPort = new QSerialPort(this);
    QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();
    for(QSerialPortInfo serialInfo : serialList)
    {
        //        qDebug() << serialInfo.portName();
        ui->comboBox_1->addItem(serialInfo.portName());
    }
    QObject::connect(serialPort, &QIODevice::readyRead, this, &Widget::SerialRecvCallback);
}


void Widget::uiMemInit()
{
    ui->comboBox_2->setCurrentIndex(7);
    ui->comboBox_3->setCurrentIndex(3);
    ui->comboBox_4->setCurrentIndex(0);
    ui->comboBox_5->setCurrentIndex(0);
    ui->comboBox_6->setCurrentIndex(0);

    ui->pushButton_sent->setEnabled(false);
    ui->checkBox_timesent->setEnabled(false);
    ui->lineEdit_mid_right_down_up->setEnabled(false);
    ui->checkBox_sentnewline->setEnabled(false);
    ui->checkBox_hexsent->setEnabled(false);
    ui->checkBox_formatinput->setEnabled(false);
    ui->checkBox_circlesent->setEnabled(false);
    ui->lineEdit_mid_right_down_up->setInputMask("999999999");

    for(int i=1; i<=9;i++)
    {
        QString buttonName = QString("pushButton_%1").arg(i);
        QPushButton* wButton = findChild<QPushButton*>(buttonName);
        if(wButton != NULL)
        {
            wButton->setProperty("buttonNum", i);
            buttonList.append(wButton);
        }

        QString textName = QString("lineEdit_%1").arg(i);
        QLineEdit *lineEdit = findChild<QLineEdit*>(textName);
        if(lineEdit != NULL)
        {
            textList.append(lineEdit);
        }

        QString checkBoxName = QString("checkBox_%1").arg(i);
        QCheckBox *checkBoxNum = findChild<QCheckBox*>(checkBoxName);
        if(checkBoxNum != NULL)
        {
            checkBoxList.append(checkBoxNum);
        }
    }

    for(QPushButton* button : buttonList)
    {
        QObject::connect(button, &QPushButton::clicked, this, [=](){on_pushButton_clicked(button->property("buttonNum").toInt());});
        button->setEnabled(false);
    }

    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, [=](){on_pushButton_sent_clicked();});

    timerRefresh = new QTimer(this);
    connect(timerRefresh,&QTimer::timeout, this, &Widget::timeRefreshPerSecFunc);
    timerRefresh->start(1000);

    timerCircle = new QTimer(this);
    QObject::connect(timerCircle, &QTimer::timeout, this, &Widget::circleSendCallBack);

    ui->comboBox_1->installEventFilter(this);
}


void Widget::on_pushButton_openorclosecom_clicked()
{

    serialPort->setPortName(ui->comboBox_1->currentText());
    serialPort->setBaudRate(ui->comboBox_2->currentText().toInt());
    serialPort->setDataBits(QSerialPort::DataBits(ui->comboBox_3->currentText().toInt()));
    switch (ui->comboBox_4->currentIndex())
    {
    case 0:
        serialPort->setParity(QSerialPort::NoParity);
        break;
    case 1:
        serialPort->setParity(QSerialPort::EvenParity);
        break;
    case 2:
        serialPort->setParity(QSerialPort::OddParity);
        break;
    case 3:
        serialPort->setParity(QSerialPort::SpaceParity);
        break;
    case 4:
        serialPort->setParity(QSerialPort::MarkParity);
        break;
    default:
        serialPort->setParity(QSerialPort::UnknownParity);
        break;
    }
    serialPort->setStopBits(QSerialPort::StopBits(ui->comboBox_5->currentText().toInt()));
    serialPort->setFlowControl(QSerialPort::NoFlowControl);
    if(serialPort->isOpen() == true)
    {
        serialPort->close();
        timer->stop();
        timerCircle->stop();
        ui->checkBox_timesent->setCheckState(Qt::Unchecked);
        ui->checkBox_circlesent->setCheckState(Qt::Unchecked);
        //        qDebug() << "serial close";
        ui->comboBox_1->setEnabled(true);
        ui->comboBox_2->setEnabled(true);
        ui->comboBox_3->setEnabled(true);
        ui->comboBox_4->setEnabled(true);
        ui->comboBox_5->setEnabled(true);
        ui->comboBox_6->setEnabled(true);

        ui->pushButton_sent->setEnabled(false);
        ui->checkBox_timesent->setEnabled(false);
        ui->lineEdit_mid_right_down_up->setEnabled(false);
        ui->lineEdit_mid_right_down_down->setEnabled(true);
        ui->checkBox_sentnewline->setEnabled(false);
        ui->checkBox_hexsent->setEnabled(false);
        ui->checkBox_formatinput->setEnabled(false);
        ui->checkBox_circlesent->setEnabled(false);
        circleSentRule(true);
        for(QPushButton* button : buttonList)
        {
            button->setEnabled(false);
        }
        ui->pushButton_openorclosecom->setText("打开串口");
        ui->label_com->setText(ui->comboBox_1->currentText() + " Closed");

    }else{
        if(serialPort->open(QIODevice::ReadWrite) == true)
        {
            //            qDebug() << "serial open success";
            ui->comboBox_1->setEnabled(false);
            ui->comboBox_2->setEnabled(false);
            ui->comboBox_3->setEnabled(false);
            ui->comboBox_4->setEnabled(false);
            ui->comboBox_5->setEnabled(false);
            ui->comboBox_6->setEnabled(false);

            ui->pushButton_sent->setEnabled(true);
            ui->checkBox_timesent->setEnabled(true);
            ui->lineEdit_mid_right_down_up->setEnabled(true);
            ui->lineEdit_mid_right_down_down->setEnabled(true);
            ui->checkBox_sentnewline->setEnabled(true);
            ui->checkBox_hexsent->setEnabled(true);
            ui->checkBox_formatinput->setEnabled(true);
            ui->checkBox_circlesent->setEnabled(true);
            for(QPushButton* button : buttonList)
            {
                button->setEnabled(true);
            }
            ui->pushButton_openorclosecom->setText("关闭串口");
            ui->label_com->setText(ui->comboBox_1->currentText() + " Opend");

        }else{
            ui->label_com->setText("Open Failed!");
            QMessageBox::warning(this, tr("出错了"), tr("打开串口出错，串口被占用或已拔出！"), QMessageBox::Ok);
        }
    }
}


void Widget::on_pushButton_sent_clicked()
{
    int wBuf = 0;
    QString sBuf = ui->lineEdit_mid_right_down_down->text();
    if(ui->checkBox_sentnewline->isChecked() == true)
    {
        sBuf += "\r\n";
    }

    if(ui->checkBox_hexsent->checkState() == Qt::Checked)
    {
        int sLen = sBuf.size();
        if(sLen % 2 != 0)
        {
            ui->label_com->setText("Error Input!");
            return;
        }
        for(QChar c : sBuf)
        {
            if(!std::isxdigit(c.toLatin1()))
            {
                ui->label_com->setText("Error Input!");
                return;
            }
        }
        wBuf = serialPort->write(QByteArray::fromHex(sBuf.toLocal8Bit()));
    }else{
        wBuf = serialPort->write(sBuf.toStdString().c_str());
    }
    if(wBuf == -1)
    {
        ui->label_com->setText("Send Error!");
    }else{
        if(ui->textEdit_historyrecord->toPlainText() == "Mr.Z-Uart_Assist")
        {
            ui->textEdit_historyrecord->clear();
        }

        sendCnt += wBuf;
        //        qDebug() << "send:" << sBuf.toStdString().c_str();
        ui->label_com->setText("Send Ok!");
        ui->label_sent->setText("Sent: " + QString::number(sendCnt));
        if(sendBak != ui->lineEdit_mid_right_down_down->text())
        {
            ui->textEdit_historyrecord->append(ui->lineEdit_mid_right_down_down->text());
            sendBak = ui->lineEdit_mid_right_down_down->text();
        }
    }
}


void Widget::SerialRecvCallback()
{
    QString rBuf = QString::fromLocal8Bit(serialPort->readAll());   //这个函数收到的是内容不是内容的size
    if(rBuf != NULL)
    {
        recvCnt += rBuf.size();
        //        () << "Get data from serial:" << rBuf;
        if(ui->checkBox_autochangeline->isChecked() == true)
        {
            rBuf += "\r\n";
        }
        if(ui->checkBox_hexdisplay->checkState() == Qt::Checked)
        {
            if(ui->checkBox_rectime->checkState() == Qt::Checked)
            {
                rBuf = "【" + getDateTime() + "】" + rBuf;
            }
            QString curBufHex = ui->textEdit_recv->toPlainText();
            QString rBufHex = QString::fromLocal8Bit(rBuf.toLocal8Bit().toHex().toUpper());
            QString tmp;
            for(int i=0; i<rBufHex.size(); i+=2)
            {
                tmp += rBufHex.mid(i,2) + " ";
            }
            ui->textEdit_recv->setText(curBufHex + tmp);
        }else{
            QTextCursor cursor = ui->textEdit_recv->textCursor();
            cursor.movePosition(QTextCursor::End);
            ui->textEdit_recv->setTextCursor(cursor);
            if(ui->checkBox_rectime->checkState() == Qt::Checked)
            {
                ui->textEdit_recv->insertPlainText("【" + getDateTime() + "】" + rBuf);
            }else{
                ui->textEdit_recv->insertPlainText(rBuf);
            }
        }
        ui->label_recv->setText("Received: " + QString::number(recvCnt));
    }
}


void Widget::on_checkBox_timesent_clicked(bool checked)
{
    if(checked == true)
    {
        timer->start(ui->lineEdit_mid_right_down_up->text().toInt());
        ui->lineEdit_mid_right_down_up->setEnabled(false);
        ui->lineEdit_mid_right_down_down->setEnabled(false);

    }else{
        timer->stop();
        ui->lineEdit_mid_right_down_up->setEnabled(true);
        ui->lineEdit_mid_right_down_down->setEnabled(true);
    }
}


void Widget::on_pushButton_clearrec_clicked()
{
    ui->textEdit_recv->clear();
    ui->label_recv->setText("Received: 0");
    ui->label_sent->setText("Sent: 0");
    sendCnt = recvCnt = 0;
}


void Widget::on_pushButton_saverec_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("另存为"), "E:/QtProject/uart_assist/untitled",\
                                                    tr("Text files (*.txt) ;; Image Files (*.png *.jpg *.bmp) ;; XML files (*.xml)"));
    if(fileName != NULL)
    {
        file.setFileName(fileName);
        int oFlag = file.open(QIODevice::WriteOnly | QIODevice::Text);
        if(oFlag == false)
        {
            //            () << "open file fault!";
            return;
        }
        QTextStream out(&file);
        out << ui->textEdit_recv->toPlainText();
    }
    file.close();
}


void Widget::timeRefreshPerSecFunc()
{
    ui->label_time->setText(getDateTime());
}

QString Widget::getDateTime()
{
#if 0
    currentTime = QDateTime::currentDateTime();
    int year = currentTime.date().year();
    int month = currentTime.date().month();
    int day = currentTime.date().day();
    int hour = currentTime.time().hour();
    int min = currentTime.time().minute();
    int sec = currentTime.time().second();

    QString serialTime = QString("%1-%2-%3 %4:%5:%6")
            .arg(year,2,10,QChar('0'))
            .arg(month,2,10,QChar('0'))
            .arg(day,2,10,QChar('0'))
            .arg(hour,2,10,QChar('0'))
            .arg(min,2,10,QChar('0'))
            .arg(sec,2,10,QChar('0'));
#endif
    currentTime = QDateTime::currentDateTime();
    QString serialTime = currentTime.toString("yyyy-MM-dd hh:mm:ss ap");
    return  serialTime;
}


void Widget::on_checkBox_hexdisplay_clicked(bool checked)
{
    if(checked == true)
    {
        QString tmp;
        QString hBuf = QString::fromLocal8Bit(ui->textEdit_recv->toPlainText().toLocal8Bit().toHex().toUpper());
        for(int i=0; i<hBuf.size(); i+=2)
        {
            tmp += hBuf.mid(i,2) + " ";
        }
        ui->textEdit_recv->setText(tmp);

    }else{
        QString sBuf = QString::fromLocal8Bit(QByteArray::fromHex(ui->textEdit_recv->toPlainText().toLocal8Bit().toLower()));
        ui->textEdit_recv->setText(sBuf);
    }
}


void Widget::on_pushButton_hidetemplate_clicked(bool checked)
{
    if(checked == true)
    {
        //                qDebug() << "status1:" << checked;
        ui->groupBox_multitext->hide();
        ui->pushButton_hidetemplate->setText("扩展面板");
    }else{
        //                qDebug() << "status2:" << checked;
        ui->groupBox_multitext->show();
        ui->pushButton_hidetemplate->setText("隐藏面板");
    }
}


void Widget::on_pushButton_hidehistory_clicked(bool checked)
{
    if(checked == true)
    {
        ui->groupBox_historyrecord->hide();
        ui->pushButton_hidehistory->setText("显示历史");
    }else{
        ui->groupBox_historyrecord->show();
        ui->pushButton_hidehistory->setText("隐藏历史");
    }
}


void Widget::on_pushButton_clicked(int num)
{
    QString sBuf = textList[num-1]->text();
    ui->lineEdit_mid_right_down_down->setText(sBuf);
    bool state = false;
    state = checkBoxList[num-1]->isChecked();
    if(ui->checkBox_sentnewline->isChecked() == true)
    {
        sBuf += "\r\n";
    }
    sendCnt += sBuf.size();
    if(state == true)
    {
        QByteArray tmp = sBuf.toLocal8Bit().toHex().toUpper();
        QByteArray transTmp;
        for(int i=0; i<tmp.size(); i+=2)
        {
            transTmp += tmp.mid(i,2) + " ";
        }
        serialPort->write(transTmp);
    }else{
        serialPort->write(sBuf.toStdString().c_str());
    }
    ui->label_sent->setText("Sent: " + QString::number(sendCnt));
}


bool Widget::eventFilter(QObject *obj, QEvent *ev)
{
    Q_UNUSED(obj);
    if(serialPort->isOpen() == false)
    {
        if(ev->type() == QEvent::MouseButtonPress)
        {
            QMouseEvent *mousePress = dynamic_cast<QMouseEvent*>(ev);
            if(mousePress->button() == Qt::LeftButton)
            {
                //               qDebug() << "this is left button pressed";
                ui->label_com->setText("Refresh Ok!");
                ui->comboBox_1->clear();
                QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();
                for(QSerialPortInfo serialInfo : serialList)
                {
                    ui->comboBox_1->addItem(serialInfo.portName());
                }
                return true;
            }
            return QWidget::eventFilter(obj, ev);
        }
    }
    return QWidget::eventFilter(obj, ev);
}


void Widget::circleSentRule(bool flag)
{
    if(serialPort->isOpen() == false)
    {
        for(QPushButton *button : buttonList)
        {
            if(button != NULL)
            {
                button->setEnabled(flag);
            }
        }
    }
    for(QLineEdit *edit : textList)
    {
        if(edit != NULL)
        {
            edit->setEnabled(flag);
        }
    }
    for(QCheckBox *box : checkBoxList)
    {
        if(box != NULL)
        {
            box->setEnabled(flag);
        }
    }
    ui->spinBox_circlesent->setEnabled(flag);
}


void Widget::on_checkBox_circlesent_clicked(bool checked)
{
    if(serialPort->isOpen() == true)
    {
        if(checked == true)
        {
            circleSentRule(false);
//            getCircleTime = ui->spinBox_circlesent->value();
          timerCircle->start(ui->spinBox_circlesent->value());
//            circleThread->start();
        }else{
            timerCircle->stop();
//            circleThread->terminate();
            circleSentRule(true);
        }
    }
}


void Widget::circleSendCallBack()
{
    static int i = 0;
    emit buttonList[i++]->clicked();
    if(i == buttonList.size())
    {
        i=0;
    }
}


void Widget::on_pushButton_save_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this,tr("保存"), "E:/QtProject/uart_assist/multiTextRecord", tr("Text(*.txt)"));
    file.setFileName(fileName);
    int oFlag = file.open(QFile::WriteOnly | QFile::Text);
    if(oFlag == false)
    {
//        qDebug() << "open textFile fault";
        return;
    }
    QTextStream out(&file);
    for(int i=0; i<textList.size(); i++)
    {
//       qDebug()<< i;
        out << checkBoxList[i]->isChecked() << "," << textList[i]->text() << "\n";
    }
    file.close();
}


void Widget::on_pushButton_load_clicked()
{
      QString fileName = QFileDialog::getOpenFileName(this,tr("载入"), "E:/QtProject/uart_assist/", tr("Text(*.txt)"));
      file.setFileName(fileName);
      int oFlag = file.open(QFile::ReadOnly | QFile::Text);
      if(oFlag == false)
      {
          return;
      }
      QTextStream in(&file);
      int i=0;
      while((in.atEnd() == false) && (i<textList.size()))
      {
         QString  tmpText = in.readLine();
         QStringList list = tmpText.split(',');
         if(list.count() == 2)
         {
             checkBoxList[i]->setChecked(list.at(0).toInt());
             textList[i]->setText(list.at(1));
             i++;
         }
      }
      file.close();
}


void Widget::on_pushButton_reset_clicked()
{
     QMessageBox msgBox;
     msgBox.setWindowTitle("提示");
     msgBox.setWindowIcon(QIcon());
     msgBox.setIcon(QMessageBox::Question);
     msgBox.setText("重置列表不可逆，确认是否重置？");
     QPushButton *yesButton = msgBox.addButton("是(Y)",QMessageBox::YesRole);
     QPushButton *noButton = msgBox.addButton("否(N)",QMessageBox::NoRole);
     msgBox.exec();
     if(msgBox.clickedButton() == yesButton)
     {
         for(QCheckBox *box : checkBoxList)
         {
             box->setChecked(false);
         }
         for(QLineEdit *edit : textList)
         {
             edit->clear();
         }
     }
}

